/**
 * Copyright 2012 Ricardo Engel
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.mookt.dcubed;

import java.io.Serializable;

/**
 * An entity is an object represented primarily by its identity and not by its
 * attributes.
 * 
 * <p>
 * As a corollary of the assertion above, two entities are considered equal if
 * their identity are the same. (See {@linkplain #equals(Object) and
 * {@linkplain #hashCode()}).
 * </p>
 * 
 * <p>
 * It is required that an entity's identity should remain the same over the
 * object's lifecycle, therefore any classes implementing this interface should
 * not provide means to change this property.
 * </p>
 * 
 * @author Ricardo Engel
 */
public interface Entity<ID extends Serializable> {

    /**
     * Returns the unique identification of this entity, regardless of its form
     * or history.
     * 
     * <p>
     * The entity's identification has be provided by an user or be an arbitrary
     * identifier created by or for the system. However, it is imperative that
     * the entity is kept the same for the entirety of this object's life. Thus,
     * concrete classes implementing this interface should <i>not</i> provide
     * means to modify this value.
     * </p>
     */
    ID getId();

    /**
     * Indicates whether some other object is "equal to" this entity.
     * 
     * <p>
     * This method must obey the general contract of
     * {@link Object#equals(Object)}. Additionally, this method can return
     * {@code true} <i>only</i> if the specified object is also an entity and
     * they have the same identification. Thus, {@code o1.equals(o2)} implies
     * that {@code o1.getId().equals(o2.getId())} for every entity reference
     * {@code o1} and {@code o2}.
     * </p>
     * 
     * <p>
     * Note that this means that for every concrete implementation of this
     * interface, the {@link #equals(Object)} method has to be overwritten.
     * </p>
     * 
     * @param obj the reference object with which to compare.
     * @return <code>true</code> only if the specified object is also an entity
     *         and they share the same identification.
     * @see Object#equals(Object)
     */
    @Override
    public boolean equals(Object obj);

    /**
     * Returns a hash code value for the entity. This method is supported for
     * the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * 
     * <p>
     * This method must obey the general contract of {@link Object#hashCode())}.
     * Additionally, two entities should have the same hash code <i>only</i> if
     * their identity also have the same hash code. Thus,
     * {@code o1.hashCode() == o2.hashCode()} implies that
     * {@code o1.getId().hashCode() == o2.getId().hashCode()} for every entity
     * reference {@code o1} and {@code o2}.
     * </p>
     * 
     * <p>
     * Note that this means that for every concrete implementation of this
     * interface, the {@link #hashCode()} method has to be overwritten.
     * </p>
     * 
     * @see Object#hashCode()
     * @return a hash code value for this object.
     */
    @Override
    public int hashCode();

}